Segurança no Backend
Este documento descreve as medidas de segurança implementadas no backend do nosso projeto. A segurança é garantida através da utilização de JWT (JSON Web Tokens) para autenticação e controle de acesso baseado em papéis (RBAC).
Controle de Acesso Baseado em Papéis (RBAC)
O que é RBAC?
RBAC, ou Role-Based Access Control, é um método de restrição de acesso a recursos com base nos papéis (roles) dos usuários dentro de uma organização. Em vez de conceder permissões diretamente a cada usuário, as permissões são atribuídas a papéis, e os usuários são atribuídos a esses papéis. Isso facilita a gestão de permissões, especialmente em sistemas grandes e complexos.
Implementação de RBAC com JWT
No nosso projeto, implementamos RBAC usando JWT para autenticação e autorização. Cada usuário, ao se autenticar, recebe um token JWT que contém informações sobre seu papel. Esse token é utilizado para validar o acesso do usuário a diferentes partes do sistema.
O que é JWT?
JWT (JSON Web Token) é um padrão aberto que define uma maneira compacta e autossuficiente de transmitir informações entre as partes como um objeto JSON. Essas informações podem ser verificadas e confiáveis porque são assinadas digitalmente.
Um JWT é composto por três partes:
- Header: Contém informações sobre o tipo de token e o algoritmo de assinatura.
- Payload: Contém as declarações (claims), que são as informações sobre uma entidade (geralmente, o usuário) e metadados adicionais.
- Signature: É a assinatura gerada a partir do header, payload e uma chave secreta. A assinatura garante que o token não foi alterado.
Como Utilizamos JWT no Nosso Sistema
-
Login do Usuário: O usuário faz login e, se autenticado com sucesso, recebe um JWT que inclui suas informações e o papel associado.
-
Durante o login, o sistema gera um JWT contendo o ID do usuário, data de expiração e emissor.
-
Exemplo de geração de JWT:
func generateJWT(user *entity.User) (string, error) {
expirationTime := time.Now().Add(72 * time.Hour) // Token expira em 72 horas
claims := &jwt.RegisteredClaims{
Subject: user.ID,
ExpiresAt: jwt.NewNumericDate(expirationTime),
Issuer: "InteliModulo10",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(os.Getenv("JWT_SECRET_KEY")))
if err != nil {
return "", err
}
return tokenString, nil
}
-
-
Verificação do JWT: Em cada requisição protegida, o middleware de autenticação verifica o JWT para garantir que o usuário tenha um token válido e que seu papel autorize o acesso ao recurso solicitado.
-
O middleware extrai o token do cabeçalho da requisição, verifica sua validade e extrai as informações contidas nele.
-
Exemplo de middleware de autenticação:
func AuthMiddleware(userRepository entity.UserRepository, requiredRole string) gin.HandlerFunc {
return func(c *gin.Context) {
tokenString, err := getTokenFromHeader(c)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
c.Abort()
return
}
claims, err := parseToken(tokenString)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
user, err := userRepository.FindUserById(claims.Subject)
if err != nil || user == nil {
handleUserError(c, err)
return
}
if user.Role != requiredRole {
c.JSON(http.StatusForbidden, gin.H{"error": "You don't have permission to access this route"})
c.Abort()
return
}
c.Set("userID", user.ID)
c.Next()
}
}
-
-
Verificação de Papel (Role): O middleware verifica se o papel do usuário é adequado para acessar a rota protegida.
- Se o papel do usuário não corresponder ao papel exigido, o acesso é negado.
Papéis no Sistema
Os papéis são definidos e controlados no banco de dados como um enum com os seguintes valores:
admin
: Usuários 'master' do sistema, com acesso total.user
: Usuários base que utilizam os serviços, como solicitar medicamentos.collector
: Responsável por receber e executar pedidos.manager
: Responsável por gerir os pedidos e também pode executá-los.
Vantagens do RBAC
- Facilidade de Gestão: Permissões são atribuídas a papéis, não diretamente aos usuários, facilitando a administração.
- Segurança: Reduz o risco de erros na atribuição de permissões, garantindo que os usuários só possam acessar o que é permitido pelo seu papel.
- Escalabilidade: Facilita a adição de novos usuários e a modificação de permissões à medida que o sistema cresce.
Desvantagens do RBAC
- Rigidez: Pode ser inflexível em sistemas onde as necessidades de acesso variam muito entre os usuários.
- Complexidade: Em sistemas muito grandes, a definição e gestão dos papéis e permissões podem se tornar complexas.
Futuras Melhorias
Para aprimorar ainda mais a segurança do sistema, planeja-se a implementação de Controle de Acesso Baseado em Atributos (ABAC).
O que é ABAC?
ABAC, ou Attribute-Based Access Control, é um método de controle de acesso que utiliza atributos (como departamento, função, tempo de acesso) para conceder permissões. Isso permite uma segurança mais granular e flexível, onde políticas complexas podem ser definidas com base em múltiplos atributos.
Vantagens do ABAC
- Flexibilidade: Permite definir políticas de acesso mais detalhadas e complexas.
- Granularidade: Permite um controle de acesso mais específico e preciso, adequado para ambientes com requisitos de segurança elevados.
Planejamento para Implementação de ABAC
A implementação do ABAC visa:
- Separar quem tem acesso a quais recursos específicos.
- Permitir uma segurança mais granular, onde ações específicas podem ser autorizadas com base em atributos do usuário, do recurso e do contexto.
Esta melhoria trará uma camada adicional de segurança, essencial para sistemas que exigem um controle de acesso mais detalhado e preciso.
Conclusão
A segurança no nosso backend é garantida atualmente através da implementação de RBAC com JWT, oferecendo uma solução robusta e escalável para controle de acesso. No futuro, planejamos evoluir para ABAC, buscando uma segurança ainda mais granular e adaptável às necessidades específicas dos usuários e recursos do sistema.